package com.tools.service.workflow.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tools.mapper.workflow.FlowInstanceMapper;
import com.tools.pojo.workflow.bo.ExecutionPath;
import com.tools.pojo.workflow.bo.PathNode;
import com.tools.pojo.workflow.po.FlowInstance;
import com.tools.service.workflow.FlowInstanceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Slf4j
@Service
@RequiredArgsConstructor
public class FlowInstanceServiceImpl extends ServiceImpl<FlowInstanceMapper, FlowInstance> implements FlowInstanceService {

    private final ObjectMapper objectMapper;

    /**
     * 创建流程实例
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public FlowInstance createInstance(Long flowDefinitionId, String businessKey, Map<String, Object> initialData) {
        FlowInstance instance = new FlowInstance();
        instance.setFlowDefinitionId(flowDefinitionId);
        instance.setBusinessKey(businessKey);
        instance.setCurrentNodeCode("START");
        instance.setCurrentStepCode(null);
        instance.setStatus(0);
        instance.setContextData(serializeContextData(initialData));

        // 初始化执行路径
        ExecutionPath executionPath = new ExecutionPath();
        executionPath.setStartTime(LocalDateTime.now().toString());
        instance.setExecutionPath(serializeExecutionPath(executionPath));

        instance.setCreateTime(LocalDateTime.now());
        instance.setUpdateTime(LocalDateTime.now());

        save(instance);
        return instance;
    }

    /**
     * 更新流程状态
     */
    @Override
    public void updateStatus(Long instanceId, Integer status) {
        FlowInstance instance = new FlowInstance();
        instance.setId(instanceId);
        instance.setStatus(status);
        instance.setUpdateTime(LocalDateTime.now());
        updateById(instance);
    }

    /**
     * 更新上下文数据
     */
    @Override
    public void updateContextData(Long instanceId, Map<String, Object> contextData) {
        FlowInstance instance = getById(instanceId);
        if (instance != null) {
            Map<String, Object> existingData = parseContextData(instance.getContextData());
            existingData.putAll(contextData);
            instance.setContextData(serializeContextData(existingData));
            instance.setUpdateTime(LocalDateTime.now());
            updateById(instance);
        }
    }

    /**
     * 更新当前步骤
     */
    @Override
    public void updateCurrentStep(Long instanceId, String stepCode) {
        FlowInstance instance = getById(instanceId);
        if (instance != null) {
            instance.setCurrentStepCode(stepCode);
            instance.setUpdateTime(LocalDateTime.now());
            updateById(instance);
        }
    }

    /**
     * 序列化上下文数据
     */
    @Override
    public String serializeContextData(Map<String, Object> contextData) {
        try {
            return objectMapper.writeValueAsString(contextData);
        } catch (Exception e) {
            log.error("序列化上下文数据失败", e);
            return "{}";
        }
    }

    /**
     * 解析上下文数据
     */
    @Override
    public Map<String, Object> parseContextData(String contextDataJson) {
        try {
            if (contextDataJson == null || contextDataJson.trim().isEmpty()) {
                return new HashMap<>();
            }
            return objectMapper.readValue(contextDataJson, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.error("解析上下文数据失败", e);
            return new HashMap<>();
        }
    }

    /**
     * 根据业务标识获取流程实例
     */
    @Override
    public FlowInstance getByBusinessKey(String businessKey) {
        return lambdaQuery()
                .eq(FlowInstance::getBusinessKey, businessKey)
                .orderByDesc(FlowInstance::getCreateTime)
                .last("LIMIT 1")
                .one();
    }

    /**
     * 获取进行中的流程实例
     */
    @Override
    public List<FlowInstance> getRunningInstances() {
        return lambdaQuery()
                .eq(FlowInstance::getStatus, 0)
                .list();
    }

    /**
     * 更新当前节点
     */
    @Override
    public void updateCurrentNode(Long instanceId, String nodeCode, String nodeName, String nodeType) {
        FlowInstance instance = getById(instanceId);
        if (instance != null) {
            instance.setCurrentNodeCode(nodeCode);

            // 如果是步骤节点，同时更新当前步骤
            if ("STEP".equals(nodeType)) {
                instance.setCurrentStepCode(nodeCode);
            }

            instance.setUpdateTime(LocalDateTime.now());
            updateById(instance);
        }
    }


    /**
     * 记录节点开始执行
     */
    @Override
    public void recordNodeStart(Long instanceId, String nodeCode, String nodeName, String nodeType) {
        FlowInstance instance = getById(instanceId);
        if (instance != null) {
            // 更新当前节点
            instance.setCurrentNodeCode(nodeCode);
            if ("STEP".equals(nodeType)) {
                instance.setCurrentStepCode(nodeCode);
            }

            // 记录到执行路径
            ExecutionPath executionPath = parseExecutionPath(instance.getExecutionPath());
            PathNode pathNode = new PathNode(nodeCode, nodeName, nodeType);
            executionPath.addNode(pathNode);

            instance.setExecutionPath(serializeExecutionPath(executionPath));
            instance.setUpdateTime(LocalDateTime.now());
            updateById(instance);
        }
    }

    /**
     * 记录节点执行完成
     */
    @Override
    public void recordNodeComplete(Long instanceId, String nodeCode, boolean success, String message, Object result) {
        FlowInstance instance = getById(instanceId);
        if (instance != null) {
            ExecutionPath executionPath = parseExecutionPath(instance.getExecutionPath());

            // 更新节点状态
            executionPath.getNodes().stream()
                    .filter(node -> nodeCode.equals(node.getNodeCode()) && node.getEndTime() == null)
                    .findFirst()
                    .ifPresent(node -> {
                        node.setEndTime(LocalDateTime.now().toString());
                        node.setSuccess(success);
                        node.setMessage(message);
                        node.setResult(result);
                    });

            // 重新计算执行路径统计
            executionPath.setTotalNodes(executionPath.getNodes().size());
            executionPath.setExecutedNodes((int) executionPath.getNodes().stream()
                    .filter(node -> node.getEndTime() != null)
                    .count());

            // 如果是结束节点，记录结束时间
            if ("END".equals(nodeCode)) {
                executionPath.setEndTime(LocalDateTime.now().toString());
                executionPath.setCompleted(true);
            }

            instance.setExecutionPath(serializeExecutionPath(executionPath));
            instance.setUpdateTime(LocalDateTime.now());
            updateById(instance);
        }
    }

    /**
     * 获取执行路径
     */
    @Override
    public ExecutionPath getExecutionPath(Long instanceId) {
        FlowInstance instance = getById(instanceId);
        if (instance != null) {
            return parseExecutionPath(instance.getExecutionPath());
        }
        return new ExecutionPath();
    }

    /**
     * 序列化执行路径
     */
    @Override
    public String serializeExecutionPath(ExecutionPath executionPath) {
        try {
            // 确保 completed 状态是最新的
            if (executionPath != null) {
                executionPath.setCompleted(executionPath.isCompleted());
            }
            return objectMapper.writeValueAsString(executionPath);
        } catch (Exception e) {
            log.error("序列化执行路径失败", e);
            return "{}";
        }
    }

    /**
     * 解析执行路径
     */
    @Override
    public ExecutionPath parseExecutionPath(String executionPathJson) {
        try {
            if (executionPathJson == null || executionPathJson.trim().isEmpty()) {
                ExecutionPath emptyPath = new ExecutionPath();
                emptyPath.setStartTime(LocalDateTime.now().toString());
                return emptyPath;
            }

            // 使用宽松的反序列化，忽略未知字段
            ExecutionPath executionPath = objectMapper.readValue(executionPathJson, ExecutionPath.class);

            // 确保执行路径的完整性
            if (executionPath.getNodes() == null) {
                executionPath.setNodes(new ArrayList<>());
            }

            // 重新计算统计信息
            executionPath.setTotalNodes(executionPath.getNodes().size());
            executionPath.setExecutedNodes((int) executionPath.getNodes().stream()
                    .filter(node -> node.getEndTime() != null)
                    .count());

            return executionPath;

        } catch (Exception e) {
            log.error("解析执行路径失败，JSON: {}", executionPathJson, e);

            // 创建新的执行路径作为回退
            ExecutionPath fallbackPath = new ExecutionPath();
            fallbackPath.setStartTime(LocalDateTime.now().toString());
            return fallbackPath;
        }
    }



}
